package cn.kent.base.unsafe;

import sun.misc.Unsafe;

/**
 * 运行报错：因为实例化Unsafe会检查是否是BootStrap加载器加载的，main函数是使用AppClassLoader加载的，将会抛出异常。
 * 解决方法：{@link cn.kent.base.unsafe.TestUnsafe2} 通过反射使用unsafe类
 */
public class TestUnsafe {

    static final Unsafe unsafe = Unsafe.getUnsafe();

    // 记录变量state在类TestUnsafe中的偏移量(2.2.2)
    static final long stateOffset;

    // 变量 (2.2.3)
    private volatile long state = 0;

    static {
        try {
            // 获取state变量在TestUnsafe中的偏移量
            stateOffset = unsafe.objectFieldOffset(TestUnsafe.class.getDeclaredField("state"));
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw new Error(e);
        }
    }

    public static void main(String[] args) {
        TestUnsafe test = new TestUnsafe();
        boolean bool = unsafe.compareAndSwapInt(test, stateOffset, 0, 1);
        System.out.println(bool);
        // 运行报错： getUnsafe() 方法会判断是不是BootStrap 加载器加载的  TestUnsafe是AppClassLoader加载的
        // rt.jar中的类时使用BootStrap加载器加载的，启动main函数的类是咋AppClassLoader加载器加载的，
        // 所以在main函数中加载Unsafe类时，根据委托机制，会委托给BootStrap去加载Unsafe类。
        // 如果没有这个限制，开发人员就可以随意使用Unsafe类操作内存，这是不安全的。
        // 可以使用反射使用Unsafe类。
    }
}
